home *** CD-ROM | disk | FTP | other *** search
/ ...taking it to the Macs! / ...taking it to the Macs!.iso / Extras / ActiveX Mac SDK / ActiveX SDK / Container Common / CActiveXScheduler.cpp < prev    next >
Text File  |  1997-01-03  |  12KB  |  434 lines

  1. // ===========================================================================
  2. //    CActiveXScheduler.cpp    ©1996 Microsoft Corporation. All rights reserved.
  3. // ===========================================================================
  4. //
  5. //    schedules Active X idle tasks
  6.  
  7. #ifdef PowerPlant_PCH
  8. #include PowerPlant_PCH
  9. #endif
  10.  
  11. #include "CActiveXScheduler.h"
  12.  
  13. CActiveXScheduler*        CActiveXScheduler::sActiveXScheduler = NULL;
  14. static Int16 CompareSchedControlStruct(SchedControlStruct *p1, SchedControlStruct *p2);
  15.  
  16. #pragma mark === CActiveXScheduler Constructor & Destructor ===
  17.  
  18. // ---------------------------------------------------------------------------
  19. //        • CActiveXScheduler::GetActiveXScheduler [static]
  20. // ---------------------------------------------------------------------------
  21. //    creates a single instance
  22.  
  23. CActiveXScheduler*
  24. CActiveXScheduler::GetActiveXScheduler(Boolean8 MakeIt)
  25. {
  26.     if (!sActiveXScheduler && MakeIt)
  27.         sActiveXScheduler = new CActiveXScheduler;
  28.  
  29.     return sActiveXScheduler;
  30. }
  31.  
  32.  
  33. // ---------------------------------------------------------------------------
  34. //        • CActiveXScheduler::CActiveXScheduler
  35. // ---------------------------------------------------------------------------
  36. //    default constructor
  37.  
  38. CActiveXScheduler::CActiveXScheduler()
  39. {
  40.     mScheduledControls = NULL;
  41.     mNeedsSorting = false;
  42. }
  43.  
  44.  
  45. // ---------------------------------------------------------------------------
  46. //        • CActiveXScheduler::~CActiveXScheduler
  47. // ---------------------------------------------------------------------------
  48. //    destructor
  49.  
  50. CActiveXScheduler::~CActiveXScheduler(void)
  51. {
  52.     if (mScheduledControls)
  53.         ::DisposeHandle(Handle(mScheduledControls));
  54. }
  55.  
  56.  
  57. #pragma mark === CActiveXScheduler Idle methods ===
  58.  
  59. // ---------------------------------------------------------------------------
  60. //        • CActiveXScheduler::Idle
  61. // ---------------------------------------------------------------------------
  62. //    give time to scheduled active x objects
  63.  
  64. ErrorCode
  65. CActiveXScheduler::Idle(Boolean8 inNullEvent)
  66. {
  67.     if (mScheduledControls)
  68.     {
  69.         if (mNeedsSorting)
  70.             Sort();
  71.  
  72.         //    give time to controls
  73.         ::HLockHi(Handle(mScheduledControls));
  74.         SchedControlStruct*    here = *mScheduledControls;
  75.         SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + ::GetHandleSize(Handle(mScheduledControls)));
  76.         Int32                CurrentTime = ::TickCount();
  77.  
  78.         while (here < end && here->WaitUntil <= CurrentTime)
  79.         {
  80.             if (here->AfterAllEvents || inNullEvent)
  81.             {
  82.                 here->Control->DoIdle(here->ControlRefCon);
  83.  
  84.                 //    reschedule the control if its waituntil time changes
  85.                 if (here->Interval > 0)
  86.                 {
  87.                     mNeedsSorting = true;
  88.                     here->WaitUntil = CurrentTime + here->Interval;
  89.                 }
  90.             }
  91.             here++;
  92.         }
  93.  
  94.         ::HUnlock(Handle(mScheduledControls));
  95.     }
  96.  
  97.     return S_OK;
  98. }
  99.  
  100.  
  101. // ---------------------------------------------------------------------------
  102. //        • CActiveXScheduler::IdleControl
  103. // ---------------------------------------------------------------------------
  104. //    give time to the one control if it is registered to want it
  105.  
  106. ErrorCode
  107. CActiveXScheduler::IdleControl(Boolean8 inNullEvent, IControl* inControl)
  108. {
  109.     if (mScheduledControls)
  110.     {
  111.         if (mNeedsSorting)
  112.             Sort();
  113.  
  114.         //    give time to the control
  115.         ::HLockHi(Handle(mScheduledControls));
  116.         SchedControlStruct*    here = *mScheduledControls;
  117.         SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + ::GetHandleSize(Handle(mScheduledControls)));
  118.         Int32                CurrentTime = ::TickCount();
  119.  
  120.         while (here < end && here->WaitUntil <= CurrentTime)
  121.         {
  122.             if ((here->AfterAllEvents || inNullEvent) && here->Control == inControl)
  123.             {
  124.                 here->Control->DoIdle(here->ControlRefCon);
  125.  
  126.                 //    reschedule the control if its waituntil time changes
  127.                 if (here->Interval > 0)
  128.                 {
  129.                     mNeedsSorting = true;
  130.                     here->WaitUntil = CurrentTime + here->Interval;
  131.                 }
  132.             }
  133.             here++;
  134.         }
  135.  
  136.         ::HUnlock(Handle(mScheduledControls));
  137.     }
  138.  
  139.     return S_OK;
  140. }
  141.  
  142.  
  143. #pragma mark === CActiveXScheduler change queue items ===
  144.  
  145. // ---------------------------------------------------------------------------
  146. //        • CActiveXScheduler::ScheduleControl
  147. // ---------------------------------------------------------------------------
  148. //    schedule a control - adding it if it isn't there, changing its time if it is
  149.  
  150. ErrorCode
  151. CActiveXScheduler::ScheduleControl(Boolean8 AfterAllEvents, Int32 Interval, IControl* inControl, Uint32 ControlRefCon)
  152. {
  153.     ErrorCode    Result = E_FAIL;
  154.     Uint32        WaitUntil = ::TickCount() + Interval;
  155.     Uint32        HandleBytes = 0;
  156.  
  157.     AfterAllEvents = AfterAllEvents ? true : false;    //    be sure there are only two possible values
  158.  
  159.     //    first see if we can just overwrite an existing record
  160.     if (mScheduledControls)
  161.     {
  162.         HandleBytes = ::GetHandleSize(Handle(mScheduledControls));
  163.  
  164.         //    I'm not going to lock handles here since I make NO function calls
  165.         SchedControlStruct*    here = *mScheduledControls;
  166.         SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + HandleBytes);
  167.  
  168.         while (Result == E_FAIL && here < end)
  169.         {
  170.             if (here->Control == inControl && here->ControlRefCon == ControlRefCon)
  171.             {
  172.                 mNeedsSorting = true;
  173.                 Result = S_OK;
  174.                 here->WaitUntil = WaitUntil;
  175.                 here->Interval = Interval;
  176.                 here->AfterAllEvents = AfterAllEvents;
  177.             }
  178.             else
  179.                 here++;
  180.         }
  181.     }
  182.  
  183.     if (Result == E_FAIL)
  184.     {
  185.         if (!mScheduledControls)
  186.             mScheduledControls = (SchedControlStruct**)::NewHandle(0);
  187.  
  188.         if (mScheduledControls)
  189.         {
  190.             ::SetHandleSize(Handle(mScheduledControls), HandleBytes + sizeof(SchedControlStruct));
  191.             if (::MemError() == noErr)
  192.             {
  193.                 //    again, no handle locking since there aren't any function calls
  194.                 SchedControlStruct*    here = (SchedControlStruct*)((Char8*)*mScheduledControls + HandleBytes);
  195.  
  196.                 mNeedsSorting = true;
  197.                 here->Control = inControl;
  198.                 here->ControlRefCon = ControlRefCon;
  199.                 here->WaitUntil = WaitUntil;
  200.                 here->Interval = Interval;
  201.                 here->AfterAllEvents = AfterAllEvents;
  202.                 Result = S_OK;
  203.             }
  204.         }
  205.     }
  206.  
  207.     return Result;
  208. }
  209.  
  210.  
  211. // ---------------------------------------------------------------------------
  212. //        • CActiveXScheduler::RemoveControlByRefCon
  213. // ---------------------------------------------------------------------------
  214. //    remove a specific control and refcon pair from the queue
  215.  
  216. ErrorCode
  217. CActiveXScheduler::RemoveControlByRefCon(IControl* inControl, Uint32 ControlRefCon)
  218. {
  219.     ErrorCode    Result = E_FAIL;
  220.  
  221.     if (mScheduledControls)
  222.     {
  223.         ::HLock(Handle(mScheduledControls));
  224.         if (::MemError() == noErr)
  225.         {
  226.             Uint32                HandleBytes = ::GetHandleSize(Handle(mScheduledControls));
  227.             SchedControlStruct*    here = *mScheduledControls;
  228.             SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + HandleBytes);
  229.  
  230.             while (Result == E_FAIL && here < end)
  231.             {
  232.                 if (here->Control == inControl && here->ControlRefCon == ControlRefCon)
  233.                 {
  234.                     Result = S_OK;
  235.                     ::BlockMove(here+1, here, (Char8*)end - (Char8*)(here+1));
  236.                     HandleBytes -= sizeof(SchedControlStruct);
  237.                 }
  238.                 else
  239.                     here++;
  240.             }
  241.             ::HUnlock(Handle(mScheduledControls));
  242.  
  243.             //    if we removed something then resize the handle down
  244.             if (Result ==  S_OK)
  245.                 ::SetHandleSize(Handle(mScheduledControls), HandleBytes);
  246.         }
  247.     }
  248.  
  249.     return Result;
  250. }
  251.  
  252.  
  253. // ---------------------------------------------------------------------------
  254. //        • CActiveXScheduler::RemoveControl
  255. // ---------------------------------------------------------------------------
  256. //    remove all items in the queue belonging the the control
  257.  
  258. ErrorCode
  259. CActiveXScheduler::RemoveControl(IControl* inControl)
  260. {
  261.     ErrorCode    Result = E_FAIL;
  262.  
  263.     if (mScheduledControls)
  264.     {
  265.         ::HLock(Handle(mScheduledControls));
  266.         if (::MemError() == noErr)
  267.         {
  268.             Uint32                HandleBytes = ::GetHandleSize(Handle(mScheduledControls));
  269.             SchedControlStruct*    here = *mScheduledControls;
  270.             SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + HandleBytes);
  271.  
  272.             while (here < end)
  273.             {
  274.                 if (here->Control == inControl)
  275.                 {
  276.                     Result = S_OK;
  277.                     ::BlockMove(here+1, here, (Char8*)end - (Char8*)(here+1));
  278.                     end--;
  279.                 }
  280.                 else
  281.                     here++;
  282.             }
  283.  
  284.             //    if we removed something then resize the handle down
  285.             HandleBytes = (Char8*)end - (Char8*)*mScheduledControls;
  286.             ::HUnlock(Handle(mScheduledControls));
  287.             if (Result ==  S_OK)
  288.                 ::SetHandleSize(Handle(mScheduledControls), HandleBytes);
  289.         }
  290.     }
  291.  
  292.     return Result;
  293. }
  294.  
  295.  
  296. #pragma mark === CActiveXScheduler query scheduler methods ===
  297.  
  298. // ---------------------------------------------------------------------------
  299. //        • CActiveXScheduler::HasNullEventItems
  300. // ---------------------------------------------------------------------------
  301. //    remove all items in the queue belonging the the control
  302.  
  303. Boolean8
  304. CActiveXScheduler::HasNullEventItems(void)
  305. {
  306.     Boolean8    Result = false;
  307.  
  308.     if (mScheduledControls)
  309.     {
  310.         //    I'm not going to lock handles here since I make NO function calls
  311.         SchedControlStruct*    here = *mScheduledControls;
  312.         SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + ::GetHandleSize(Handle(mScheduledControls)));
  313.  
  314.         while (!Result && here < end)
  315.         {
  316.             Result = !here->AfterAllEvents;
  317.             here++;
  318.         }
  319.     }
  320.  
  321.     return Result;
  322. }
  323.  
  324.  
  325. // ---------------------------------------------------------------------------
  326. //        • CActiveXScheduler::HasAllEventItems
  327. // ---------------------------------------------------------------------------
  328. //    remove all items in the queue belonging the the control
  329.  
  330. Boolean8
  331. CActiveXScheduler::HasAllEventItems(void)
  332. {
  333.     Boolean8    Result = false;
  334.  
  335.     if (mScheduledControls)
  336.     {
  337.         Uint32                HandleBytes = ::GetHandleSize(Handle(mScheduledControls));
  338.  
  339.         //    I'm not going to lock handles here since I make NO function calls
  340.         SchedControlStruct*    here = *mScheduledControls;
  341.         SchedControlStruct* end = (SchedControlStruct*)((Char8*)here + ::GetHandleSize(Handle(mScheduledControls)));
  342.  
  343.         while (!Result && here < end)
  344.         {
  345.             Result = here->AfterAllEvents;
  346.             here++;
  347.         }
  348.     }
  349.  
  350.     return Result;
  351. }
  352.  
  353.  
  354. #pragma mark === CActiveXScheduler private methods ===
  355.  
  356. // ---------------------------------------------------------------------------
  357. //        • CActiveXScheduler::Sort
  358. // ---------------------------------------------------------------------------
  359. //    sort the job schedule queue - use a bubble sort since the queue shouldn't
  360. //    be very long nor very out of order
  361.  
  362. void
  363. CActiveXScheduler::Sort(void)
  364. {
  365.     Uint32    ItemCount;
  366.  
  367.     if (mNeedsSorting && (!mScheduledControls ||
  368.             (ItemCount = ::GetHandleSize(Handle(mScheduledControls))/sizeof(SchedControlStruct)) <= 1))
  369.         mNeedsSorting = false;
  370.  
  371.     if (mNeedsSorting)
  372.     {
  373.         SchedControlStruct    *p1, *p2;
  374.         SchedControlStruct    *begin = *mScheduledControls;
  375.         SchedControlStruct    *end = begin + ItemCount - 1;
  376.  
  377.         while (begin < end)
  378.         {
  379.             SchedControlStruct    *newEnd = NULL;
  380.             for (p1 = begin, p2 = begin + 1; p2 <= end; p1++, p2++)
  381.             {
  382.                 SchedControlStruct    Temp;
  383.  
  384.                 if (CompareSchedControlStruct(p1, p2) > 0)
  385.                 {
  386.                     Temp = *p1;
  387.                     *p1 = *p2;
  388.                     *p2 = Temp;
  389.                     newEnd = p1;
  390.                 }
  391.             }
  392.             end = newEnd;
  393.         }
  394.  
  395.         mNeedsSorting = false;
  396.     }
  397. }
  398.  
  399.  
  400. #pragma mark === static function ===
  401.  
  402. // ---------------------------------------------------------------------------
  403. //        • CompareSchedControlStruct
  404. // ---------------------------------------------------------------------------
  405. //    comparison function - sort order is (WaitUntil ascending, NullOnly, Job, JobRefCon)
  406.  
  407. Int16 CompareSchedControlStruct(SchedControlStruct *p1, SchedControlStruct *p2)
  408. {
  409.     Int32                ReturnValue = 1;
  410.  
  411.     if (p1->WaitUntil < p2->WaitUntil)
  412.         ReturnValue = -1;
  413.     else if (p1->WaitUntil == p2->WaitUntil)
  414.     {
  415.         if (p1->AfterAllEvents && !p2->AfterAllEvents)
  416.             ReturnValue = -1;
  417.         else if (p1->AfterAllEvents == p2->AfterAllEvents)
  418.         {
  419.             if (p1->Control < p2->Control)
  420.                 ReturnValue = -1;
  421.             else if (p1->Control == p2->Control)
  422.             {
  423.                 if (p1->ControlRefCon < p2->ControlRefCon)
  424.                     ReturnValue = -1;
  425.                 else if (p1->ControlRefCon == p2->ControlRefCon)
  426.                     ReturnValue = 0;
  427.             }
  428.         }
  429.     }
  430.  
  431.     return ReturnValue;
  432. }
  433.  
  434.